package edu.usm.predatorwars;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Scanner;
import java.util.UUID;

import edu.predatorwars.shared.models.GameInfo;

public class App {

	private ClientMask clientmask;
	private Scanner scanner;
	private List<GameInfo> gameList;

	public App(ClientMask clientmask) {
    	this.clientmask = clientmask;
    }

	private void enterCommandLoop() {
		scanner = new Scanner(System.in);
		System.out.println("Type help for a list of commands");
		boolean exit = false;
		
		while(!exit) {
			System.out.print(">>");
			String line = scanner.nextLine();
			
			if (line.equals("exit")) {
				exit = true;
			} else if (line.equals("help")) {
				printHelpContents();
			} else if (line.startsWith("join")) {
				handleJoinCommand(line);
			} else if (line.equals("create")) {
				handleCreateCommand();
			} else if (line.equals("refresh")) {
				handleRefreshCommand();
			} else {
				System.out.println("Unrecognized command. Use help for more info");
			}
		}
	}

	private void printHelpContents() {
		System.out.println("create => Create a game (and implicitly join it)");
		System.out.println("refresh => Refresh Game list");
		System.out.println("join <game index> => Join a game");
		System.out.println("exit => Exit the game");
	}	

	private void handleJoinCommand(String line) {
		String[] tokens = line.split(" ");
		if (tokens.length != 2) {
			System.out.println("join command takes exactly 1 argument. Use help for more information");
		} else {
			try {
				int index = Integer.parseInt(tokens[1]);
				if (index < 0 || index >= gameList.size()) {
					System.out.println("game index is out of range");
				} else {
					joinGame(gameList.get(index).getGameId());
				}
			} catch(NumberFormatException e) {
				System.out.println(tokens[1] + " is not an integer");
			}
		}
	}

	private void joinGame(UUID gameId) {
		System.out.println("Joining game...");
		clientmask.joinGame(gameId, new PlayableImpl(scanner, System.out));
	}
	
	private void handleCreateCommand() {
		System.out.println("Creating and joing game...");
		clientmask.createGame(new PlayableImpl(scanner, System.out));
	}
	
	private void handleRefreshCommand() {
		gameList = clientmask.refreshGameList();
		if (gameList.isEmpty()) {
			System.out.println("Did not find any games on Game Host");
		} else {
			System.out.println("Found " + gameList.size() + " games on Game Host:");
			int cnt = 0;
			for(GameInfo game : gameList) {
				System.out.println(cnt + ": " + game.getMapName() 
						+ " " + game.getCurrentPlayers() + "/" 
						+ game.getMaxPlayers());
				cnt++;
			}
		}
	}

    public static void main( String[] args ) throws UnknownHostException {
    	System.out.println("Predator Wars command line client");
    	String gameHostUrl = getGameHostUrl();
    	String port = getLocalWebServerPort();

        App application = new App(buildClientMask(port, gameHostUrl));
        application.enterCommandLoop();
    }

	private static String getGameHostUrl() {
		String hostUrl = "http://localhost:8080";
		URL url = null;
        while (url == null) {
            System.out.print("Enter URL of Game Host Server (" + hostUrl + "):");
            Scanner scan = new Scanner(System.in);
            String line = scan.nextLine();
            if (line.isEmpty()) {
            	return hostUrl;
            }
            
        	try {
				url = new URL(line);
			} catch (MalformedURLException e) {
				System.out.println("Invalid Game Host URL");
			}
        }
        
        return url.toString();
	}


	private static String getLocalWebServerPort() {
		String port = "8085";
		Integer inputPort = null;
		while(inputPort == null) {
			System.out.print("Enter port number to use for local web server (8085):");
			Scanner scan = new Scanner(System.in);
			String line = scan.nextLine();
			if (line.isEmpty()) {
				return port;
			}
			try {
				inputPort = Integer.parseInt(line);
			} catch (NumberFormatException e) {
				System.out.println("Bad input value. Port should be a number");
			}
		}
		
		return inputPort.toString();
	}
	
	
	private static ClientMask buildClientMask(String port, String host) throws UnknownHostException {
		ClientMaskBuilder builder = new ClientMaskBuilder(host);
		return builder.hostPort(port).build();
	}
}
